//
//  DrivesMgr.m
//  carcareIOS
//
//  Created by tianxing on 16/3/7.
//  Copyright © 2016年 baozun. All rights reserved.
//

#import "DrivesMgr.h"
#import "AILDCalendar.h"
#import "NetHome.h"
#import "CalendarMgr.h"
#import "AIUserInfo.h"
#import "NetDrives.h"
#import "OneWayMgr.h"

@interface DrivesMgr()

@property (nonatomic, strong) NSMutableArray *loadedMonth;
@property (nonatomic, strong) NSMutableDictionary *loadedMonthDay;

@property (nonatomic, strong) AILDCalendar *localData;

@property (nonatomic, strong) NSMutableDictionary *drivesTMP;

@property (nonatomic, strong) NSMutableArray *loadDays;

@property (nonatomic, strong) NSMutableArray *preloadDays;

@property (nonatomic, assign) BOOL isLoading;

@end

@implementation DrivesMgr

IMP_SINGLETON

- (void)dealloc{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.loadedMonthDay = [NSMutableDictionary dictionaryWithCapacity:31];
        self.loadedMonth = [NSMutableArray arrayWithCapacity:2];
        self.drivesTMP = [NSMutableDictionary dictionaryWithCapacity:5];
        self.localData = [[AILDCalendar alloc] init];
        self.loadDays = [NSMutableArray arrayWithCapacity:10];
        self.preloadDays = [NSMutableArray arrayWithCapacity:10];
        
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(clearTMPData) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
        
    }
    return self;
}

-(void)clearTMPData{
    [self.loadedMonthDay removeAllObjects];
    [self.loadedMonth removeAllObjects];
    [self.drivesTMP removeAllObjects];
}

#pragma mark -

-(BOOL)isDrivesInDate:(NSString *)date{
    CalendarWayModel *model = self.loadedMonthDay[date];
    if ([date isEqualToString:[CALENDARMGR currentDay]] && self.drivesTMP[date]) {
        return ((DrivesModel *)self.drivesTMP[date]).travels.count > 0;
    }
    return model.drivingMark > 0 || model.status == CALENDARWAY_DRIVE || model.status == CALENDARWAY_DRIVE_ABNORMAL;
}

-(void)drivesWithDate:(NSString *)date finish:(void (^)(DrivesModel *))finish{
    
    if (finish) {
        if (self.drivesTMP[date]) {
            finish(self.drivesTMP[date]);
            if ([date isEqualToString:CALENDARMGR.currentDay]) {
                NSString *lastDate = self.preloadDays.lastObject;
                [self.preloadDays removeAllObjects];
                if ([lastDate isNotNil]) [self.preloadDays addObject:lastDate];
                if (![lastDate isEqualToString:date]) [self.preloadDays addObject:date];
            }
        }else{
            if (self.preloadDays.count > 0) {
                NSString *lastDate = self.preloadDays.lastObject;
                [self.preloadDays removeAllObjects];
                [self.preloadDays addObject:lastDate];
                if (![lastDate isEqualToString:date]) [self.preloadDays addObject:date];
                finish(nil);
            }else{
                [self.preloadDays addObject:date];
                finish(nil);
            }
        }
    }
}

-(void)loadPreloadDays{
    
    if (self.isLoading) {
        return;
    }
    __weak __typeof(self) wself = self;
    self.isLoading = YES;
    __block BOOL isOver = NO;
    
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
        dispatch_semaphore_t semap = dispatch_semaphore_create(0);
        
        while (!isOver) {
            [wself loadLastPreloadDayFinish:^{
                dispatch_semaphore_signal(semap);
            } end:^{
                isOver = YES;
                dispatch_semaphore_signal(semap);
            }];
            dispatch_semaphore_wait(semap, DISPATCH_TIME_FOREVER);
        }
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if (wself.LoadDayOK) {
                wself.LoadDayOK();
            }
            wself.isLoading = NO;
        });
        
    });
}

-(void)loadLastPreloadDayFinish:(void(^)())finish end:(void (^)())end{
    if (self.preloadDays.count > 0) {

        NSString *date = self.preloadDays.lastObject;
        __weak __typeof(self) wself = self;
        [[NetDrives drivesWithDate:date] requestSuccess:^(id JSON) {
            [wself.preloadDays removeObject:date];
            DrivesModel *model = [[DrivesModel alloc] initWithDic:JSON];
            wself.drivesTMP[date] = model;
            
            if (finish) {
                finish();
            }
        } failure:^(id JSON) {
            [wself.preloadDays removeObject:date];
            if (finish) {
                finish();
            }
        }];
    }else{
        if (end) {
            end();
        }
    }
}

#pragma mark - day

-(void)startDayWithDate:(NSDate *)date{
    [self.loadDays removeAllObjects];
    [self.loadDays addObject:date];
    self.dayIndex = 0;
}

-(void)loadNextDayFinish:(void (^)(NSInteger fromRow,NSInteger toRow))finish{
    if (self.dayIndex < self.loadDays.count - 1) {
        if (finish) {
            finish(self.dayIndex,self.dayIndex + 1);
        }
    }else {
        NSDate *date = self.loadDays[self.dayIndex];
        NSDate *nextDate = [CalendarMgr dateFromDate:date afterDays:1];
        [self.loadDays addObject:nextDate];
        if (finish) {
            finish(self.dayIndex,self.dayIndex + 1);
        }
    }
}

-(void)loadLastDayFinish:(void (^)(NSInteger fromRow,NSInteger toRow))finish{
    if (self.dayIndex > 0) {
        if (finish) {
            finish(self.dayIndex,self.dayIndex - 1);
        }
    }else {
        NSDate *date = self.loadDays[self.dayIndex];
        NSDate *lastDate = [CalendarMgr dateFromDate:date beforeDays:1];
        [self.loadDays insertObject:lastDate atIndex:0];
        if (finish) {
            finish(1,0);
        }
    }
}

#pragma mark - calendar

-(void)calendarWayInfosWithYear:(NSInteger)year month:(NSInteger)month loadFirst:(void (^)())loadFirst{
    NSString *searchDate = [NSString stringWithFormat:@"%zd-%02zd",year,month];
    if ([self.loadedMonth containsObject:searchDate]) {

    }else{
        if ([self.localData needLoadFromNetWithYear:year month:month]) {
            __weak __typeof(self) wself = self;
            [self infosFromNetWithYear:year month:month finish:^(NSArray *infos) {
                if (loadFirst) loadFirst();
                NSInteger theYear = year;
                NSInteger theMonth = month - 1;
                if (theMonth < 0) {
                    theMonth = 12;
                    theYear--;
                }
                [wself infosFromNetWithYear:theYear month:theMonth finish:nil];
            }];
        }else{
            __weak __typeof(self) wself = self;
            [self infosFromDBWithSearchDate:searchDate finish:^(NSArray *infos) {
                if (infos) {
                    if (loadFirst) loadFirst();
                }else{
                    [wself infosFromNetWithYear:year month:month finish:^(NSArray *infos) {
                        if (loadFirst) loadFirst();
                    }];
                }
            }];
        }
    }
}

-(void)infosFromNetWithYear:(NSInteger)year month:(NSInteger)month finish:(void(^)(NSArray *infos))finish{
    
    __weak __typeof(self) wself = self;
    [[[NetHome getCalendarInfoWithDate:[NSString stringWithFormat:@"%zd%02zd",year,month]] requestWithLoad:RequestLoadShowErrorTips] requestSuccess:^(id JSON) {
        NSInteger max = [CALENDARMGR daysInYear:year month:month];
        NSMutableArray *tmp = [NSMutableArray arrayWithCapacity:max];
        NSMutableArray *jsons = [NSMutableArray arrayWithCapacity:max];
        
        NSDictionary *infos = JSON[@"info"];
        
        for (int i = 1; i <= max; i++) {
            CalendarWayModel *model;
            NSString *dateString = [NSString stringWithFormat:@"%zd-%02zd-%02zd",year,month,i];
            if (infos[dateString]) {
                model = [[CalendarWayModel alloc] initWithDic:infos[dateString]];
            }else{
                model = [[CalendarWayModel alloc] init];
                model.status = CALENDARWAY_NODATA;
            }
            model.dateString = dateString;
            
            [tmp addObject:model];
            [jsons addObject:model.jsonObjectDic];
            [wself.loadedMonthDay setObject:model forKey:dateString];
        }
        
        [wself.localData.dbCalendarWay addDatas:jsons];
        [wself.localData updateSavedMonthWithYear:year month:month];
        [wself.loadedMonth addObject:[NSString stringWithFormat:@"%zd-%02zd",year,month]];
        if (finish) {
            finish(tmp);
        }
    } failure:^(id JSON) {
        if (finish) {
            finish(nil);
        }
    }];
}

-(void)infosFromDBWithSearchDate:(NSString *)searchDate finish:(void (^)(NSArray *infos))finish{
    NSArray *infos = [self.localData.dbCalendarWay datasWithSearchDate:searchDate];
    if (infos.count > 0) {
        NSMutableArray *tmp = [NSMutableArray arrayWithCapacity:infos.count];
        for (int i = 0; i < infos.count; i++) {
            CalendarWayModel *model = [[CalendarWayModel alloc] initWithDic:infos[i]];
            [tmp addObject:model];
            [self.loadedMonthDay setObject:model forKey:model.dateString];
        }
        [self.loadedMonth addObject:searchDate];
        if (finish) {
            finish(tmp);
        }
    }else{
        if (finish) {
            finish(nil);
        }
    }
}

#pragma mark - set get
-(NSArray *)days{
    return self.loadDays;
}

@end
